#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h> //可能定义了pid_t
#include <stdlib.h>
#include <string.h>


//目的是写一个函数，fork子进程，然后exec另一个程序，在同个shell中输出，子进程会输出到一个文本中，父子通信用pipe

int p[2];
int state;
char* PWD;
char* exec_name = "/test2";
char* exec_dir;

int main(int argc , char* argv[], char* envp[]){
	char cwd[1024];
	pipe(p);
	char* content;
	int fd;
	
	if(argc != 2){  // 防止段错误
		printf("usage %s <file>\n",argv[0]);
		return -1;
	}
	
	content = argv[1];
	if(fork()==0){ //子进程
	
		printf("child\n");
		
		/*----得到第二个程序的绝对路径----start*/
		PWD = getenv("PWD");//获取当前程序所在路径
		exec_dir = (char *)malloc(strlen(PWD)+strlen(exec_name));  //一个进程在结束后，linux操作系统可以自动回收该堆内存，因此无需担心没有free
		strcpy(exec_dir,PWD);
		strcat(exec_dir,exec_name);
		/*----得到第二个程序的绝对路径----end*/

		chdir("..");
		exec_dir = "try_code/test2";

		close(0);//关闭文件描述符0，即无法用0来控制标准输入
		dup(p[0]);//疑问点：p[0]在dup前后值是否发生改变？答：不变！  
			//由于前面关闭了0，此时dup后会生成一个新的文件描述符，通常会从0开始往上找，遇到可用的文件描述符就返回那个可用的值，此处就是返回0
			//然而GPT说此处因为p[0]这个文件描述符已经和0指向同个文件，所以函数返回的文件描述符0就不那么重要了，因此也没有用一个int fd去记录。
		close(p[0]);//关闭 `p` 中的读描述符
		close(p[1]);//关闭 `p` 中的写描述符
		execve(exec_dir, argv,envp);
		
		exit(2);//并不会执行到这里
		
	}
	else {  //父进程
	
		write(p[1], "from parent\n", 12); //向管道中写数据，
		write(p[1],content,strlen(content));
		write(p[1], "after content\n",14);
		close(p[0]);
		close(p[1]);
		
		wait(&state);
		printf("this is child exit state : %d \n",state);
		
		
	}

	return 0;
}

